﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using Vit.Common;

namespace Vit.Data
{
    public class DbTransactionWrapper : DbTransaction
    {
        private DbConnectionWrapper wrappedConnection;
        private DbTransaction wrappedTransaction;
        private List<string> affectedEntityNames;

        public DbTransactionWrapper(DbTransaction transaction, DbConnectionWrapper connection)
        {
            this.wrappedTransaction = transaction;
            this.wrappedConnection = connection;
            affectedEntityNames = new List<string>();
        }

        public override void Commit()
        {
            wrappedTransaction.Commit();

            TransactionEventArgs e = new TransactionEventArgs();
            e.AffectedEntities.AddRange(this.affectedEntityNames);
            e.TransactionStatus = TransactionStatus.Committed;
            foreach (IDbConnectionVisitor visitor in DbConnectionVisitorManager.Visitors)
            {
                if (visitor.IsVisiting(wrappedConnection))
                    visitor.OnTransactionCommit(this, e);
            }
        }

        protected override DbConnection DbConnection
        {
            get { return wrappedConnection; }
        }

        public override IsolationLevel IsolationLevel
        {
            get { return wrappedTransaction.IsolationLevel; }
        }

        public override void Rollback()
        {
            wrappedTransaction.Rollback();

            TransactionEventArgs e = new TransactionEventArgs();
            e.AffectedEntities.AddRange(this.affectedEntityNames);
            e.TransactionStatus = TransactionStatus.Rollbacked;
            foreach (IDbConnectionVisitor visitor in DbConnectionVisitorManager.Visitors)
            {
                if (visitor.IsVisiting(wrappedConnection))
                    visitor.OnTransactionRollback(this, e);
            }
        }

        public DbTransaction DbTransaction
        {
            get { return wrappedTransaction; }
        }

        public List<string> AffectedEntities
        {
            get { return affectedEntityNames; }
        }

        internal void AddAffectedEntities(IEnumerable<string> names)
        {
            foreach (string name in names)
            {
                if (affectedEntityNames.Contains(name))
                    continue;
                affectedEntityNames.Add(name);
            }
        }
    }
}
